package com.inno.auth.domain.service.impl;


import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil;
import com.inno.auth.common.entity.PageResult;
import com.inno.auth.common.enums.IsDeletedFlagEnum;
import com.inno.auth.common.enums.YesOrNoEnum;
import com.inno.auth.common.error.AuthException;
import com.inno.auth.common.utils.DateUtils;
import com.inno.auth.domain.convert.PlannerUsersConverter;
import com.inno.auth.domain.entity.PlannerUsersBO;
import com.inno.auth.domain.service.UsersDomainService;
import com.inno.auth.domain.strategy.LoginHandlerFactory;
import com.inno.auth.domain.utils.Md5Utils;
import com.inno.auth.domain.utils.WechatUtil;
import com.inno.auth.infra.basic.entity.PlannerUsers;
import com.inno.auth.infra.basic.service.PlannerUsersService;
import com.inno.auth.infra.rpc.SmsRpc;
import com.inno.sms.dto.SmsInfoDTO;
import com.inno.sms.enums.SmsTypeEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Random;

/**
 * @author sean
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UsersDomainServiceImpl implements UsersDomainService {
    private final PlannerUsersService plannerUsersService;
    private final WechatUtil wechatUtil;
    private final SmsRpc smsRpc;
    private final LoginHandlerFactory loginHandlerFactory;
    @Override
    public PlannerUsersBO login(PlannerUsersBO plannerUsersBO) {
        PlannerUsers plannerUsers = PlannerUsersConverter.INSTANCE.convertBOtoEntity(plannerUsersBO);
        plannerUsers.setWechatCode(plannerUsersBO.getWechatCode());
        plannerUsers.setCode(plannerUsersBO.getCode());
        PlannerUsers entity = this.loginHandlerFactory.getHandler(plannerUsersBO.getType()).login(plannerUsers);

        return convertEntityToBO(entity);
    }

    @Override
    public PlannerUsersBO getUserInfo(PlannerUsersBO bo) {
        PlannerUsers plannerUsers = this.plannerUsersService.queryById(bo.getId());
        log.info("infra层查出用户信息:{}", plannerUsers);

        return  convertEntityToBO(plannerUsers);
    }
    private PlannerUsersBO convertEntityToBO( PlannerUsers plannerUsers){
        PlannerUsersBO bo = new PlannerUsersBO();
        BeanUtil.copyProperties(plannerUsers,bo);
        log.info("domain层返回的bo:{}", bo);
        return bo;
    }

    @Override
    public List<PlannerUsersBO> getUserInfoByIdList(List<Long> idList) {
        List<PlannerUsers> usersList = this.plannerUsersService.queryByIdList(idList);

        return PlannerUsersConverter.INSTANCE.convertEntityListToBOList(usersList);
    }

    @Override
    public void register(PlannerUsersBO plannerUsersBO) {
        // 校验验证码
        SmsInfoDTO smsInfoDTO = new SmsInfoDTO();
        smsInfoDTO.setSmsContent(plannerUsersBO.getCode());
        smsInfoDTO.setMobile(plannerUsersBO.getMobile());
        smsInfoDTO.setUserId(plannerUsersBO.getId());
        PlannerUsers users = this.plannerUsersService.queryByMobile(plannerUsersBO.getMobile());
        if (Objects.nonNull(users)){
            throw new AuthException("手机号已被注册");
        }

        boolean validate = this.smsRpc.validate(smsInfoDTO);
        if (!validate){
            throw new AuthException("验证码无效");
        }
        PlannerUsers plannerUsers = PlannerUsersConverter.INSTANCE.convertBOtoEntity(plannerUsersBO);
        PlannerUsers byUsername = this.plannerUsersService.queryByUsername(plannerUsers);
        if (Objects.nonNull(byUsername)){
            throw new AuthException("用户名已被占用");
        }
        plannerUsers.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode().toString());
        plannerUsers.setCreateTime(DateUtils.getNowDate());
        plannerUsers.setPassword(Md5Utils.create().digestHex(plannerUsersBO.getPassword()));
        plannerUsers.setRegisterTime(DateUtils.getNowDate());
        plannerUsers.setId(IdUtil.getSnowflakeNextId());
        plannerUsers.setGender(YesOrNoEnum.YES.getCode());
        this.plannerUsersService.insert(plannerUsers);

    }

    @Override
    public void sendRegisterSms(PlannerUsersBO plannerUsersBO) {
        SmsInfoDTO smsInfoDTO = this.createSmsInfoDTO(plannerUsersBO);
//        PlannerUsers users = this.plannerUsersService.queryByMobile(plannerUsersBO.getMobile());
//        if (Objects.nonNull(users)){
//            throw new AuthException("手机号已被注册");
//        }
        this.smsRpc.sendSms(smsInfoDTO);
    }

    @Override
    public void update(PlannerUsersBO bo) {
        PlannerUsers users = PlannerUsersConverter.INSTANCE.convertBOtoEntity(bo);
        if (!StringUtils.isBlank(bo.getPassword())){
            users.setPassword(Md5Utils.create().digestHex(bo.getPassword()));
        }
        this.plannerUsersService.update(users);
    }

    @Override
    public void cancelAccount(PlannerUsersBO bo) {
        PlannerUsers users = PlannerUsersConverter.INSTANCE.convertBOtoEntity(bo);
        users.setIsDeleted(YesOrNoEnum.YES.getCode());
        users.setDeletedTime(DateUtils.getNowDate());
        users.setUpdateBy(users.getId());
        users.setUpdateTime(DateUtils.getNowDate());
        this.plannerUsersService.update(users);
    }

    @Override
    public PlannerUsersBO adminLogin(PlannerUsersBO plannerUsersBO) {
        PlannerUsers plannerUsers = PlannerUsersConverter.INSTANCE.convertBOtoEntity(plannerUsersBO);
        plannerUsers.setPassword(Md5Utils.create().digestHex(plannerUsers.getPassword()));
        PlannerUsers usersDB = this.plannerUsersService.queryByUsername(plannerUsers);
        if (!usersDB.getId().equals(3L)){
            throw new AuthException("无权限进入");
        }
        if (!usersDB.getPassword().equals(plannerUsers.getPassword())){
            throw AuthException.of("登录失败 登录信息填写有误");
        }
        return convertEntityToBO(usersDB);
    }

    @Override
    public Long todayRegisterCount() {
        PlannerUsers users = new PlannerUsers();
        users.setRegisterTime(DateUtils.getNowDate());
        users.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode().toString());
        return this.plannerUsersService.queryTodayRegisterCount(users);
    }

    @Override
    public Long totalRegisterCount() {
        PlannerUsers users = new PlannerUsers();
        users.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode().toString());
        return this.plannerUsersService.queryCount(users);
    }

    @Override
    public PageResult<PlannerUsersBO> queryPage(PlannerUsersBO plannerUsersBO) {
        PlannerUsers users = PlannerUsersConverter.INSTANCE.convertBOtoEntity(plannerUsersBO);
        int page = plannerUsersBO.getPage();
        int pageSize = plannerUsersBO.getPageSize();
        int offset = (page - 1) * pageSize;
        Long pageCount = this.plannerUsersService.queryCount(users);
        List<PlannerUsers> entityResult = this.plannerUsersService.queryPage(users, offset, pageSize);
        List<PlannerUsersBO> plannerUsersBOS = PlannerUsersConverter.INSTANCE.convertEntityListToBOList(entityResult);
        return PageResult.of(plannerUsersBOS, pageCount);
    }


    @Override
    public SaResult check(String wechatCode) {
        String openId = wechatUtil.getOpenId(wechatCode);
        PlannerUsers users = this.plannerUsersService.queryByOpenId(openId);
        if (Objects.nonNull(users)){
            // 注册过 直接登录
            StpUtil.login(users.getId());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            return SaResult.ok().setData(tokenInfo);
        }else {
            // 没注册过 返回空result
            return SaResult.error().setMsg("none");
        }
    }

    @Override
    public void sendBindSms(PlannerUsersBO plannerUsersBO) {
        String mobile = plannerUsersBO.getMobile();
        PlannerUsers users = this.plannerUsersService.queryByMobile(mobile);
        if (ObjUtil.isNotNull(users)){
            throw AuthException.of("手机号已被注册");
        }
        String code = generateCode();
        SmsInfoDTO smsInfoDTO = new SmsInfoDTO();
        smsInfoDTO.setSmsContent(code);
        smsInfoDTO.setSmsType(SmsTypeEnum.LOGIN_REGISTER.getCode());
        smsInfoDTO.setMobile(mobile);
        smsInfoDTO.setIsUse(YesOrNoEnum.NO.getCode());
        this.smsRpc.sendSms(smsInfoDTO);
    }

    /**
     * 绑定手机号
     */
    @Override
    public synchronized void bindMobile(PlannerUsersBO plannerUsersBO) {
        PlannerUsers users = this.plannerUsersService.queryByMobile(plannerUsersBO.getMobile());
        if (ObjUtil.isNotNull(users)){
            throw AuthException.of("手机号已被注册");
        }
        PlannerUsers entity = PlannerUsersConverter.INSTANCE.convertBOtoEntity(plannerUsersBO);
        entity.setMobile(plannerUsersBO.getMobile());

        entity.setUpdateTime(DateUtils.getNowDate());
        entity.setId(plannerUsersBO.getId());
        this.plannerUsersService.update(entity);
    }

    private static String generateCode() {
        Random random = new Random();
        int code = random.nextInt(9000) + 1000;
        return String.valueOf(code);
    }
    private SmsInfoDTO createSmsInfoDTO(PlannerUsersBO bo){
        SmsInfoDTO smsInfoDTO = new SmsInfoDTO();
        String code = generateCode();
        smsInfoDTO.setSmsContent(code);
        smsInfoDTO.setMobile(bo.getMobile());
        smsInfoDTO.setUserId(bo.getId());
        smsInfoDTO.setSmsType(SmsTypeEnum.LOGIN_REGISTER.getCode());
        smsInfoDTO.setIsUse(YesOrNoEnum.NO.getCode());
        return smsInfoDTO;
    }
}
